package com.aggregate.pay.weixin.support;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aggregate.pay.weixin.bean.AbstractData;
import com.aggregate.pay.weixin.bean.SignResult;
import com.aggregate.pay.weixin.support.utils.MD5;
import com.aggregate.pay.weixin.support.utils.XML;

/**
 * 接口API操作类抽象类
 * 
 * @author Moyq5
 * @date 2017年6月15日
 * @param <D>
 * @param <R>
 */
public abstract class AbstractClient<D extends AbstractData, R extends SignResult> implements Client<D, R> {

	private static Logger log = LoggerFactory.getLogger(AbstractClient.class);
	
	private HttpClient client;
	private Merch merch;
	public AbstractClient(Merch merch) {
		this.merch = merch;
	}
	@Override
	public R execute(D data) {
		R r = null;
		try {
			data.setAppId(merch.appId());
			data.setMchId(merch.mchId());
			data.setSubAppId(merch.subAppId());
			data.setSubMchId(merch.subMchId());
			data.setNonceStr(MD5.MD5Encode(String.valueOf(Math.random())));
			data = Tool.sign(data, merch.apiKey());
			String reqBody = XML.toXml(data);
			String resBody = httpClient().post(getApiPath(), reqBody);
			r = XML.toObject(resBody, getResultClass());

			if (r.getReturnCode().equals("SUCCESS")) {
				String sign = Tool.sign(resBody, merch.apiKey());
				if (!sign.equals(r.getSign())) {
					log.warn("验签失败：源值[{}]!=实际值[{}]", sign, r.getSign());
					throw new Exception("签名失败");
				}
				log.debug("签名验证通过");
			}
			
		} catch (Exception e) {
			log.error("接口调用失败", e);
			try {
				r = getResultClass().newInstance();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			r.setReturnCode("FAIL");
			r.setReturnMsg(e.getMessage());
		}
		return r;
	}
	
	protected abstract Class<R> getResultClass();
	
	protected abstract String getApiPath();
	
	@Override
	public void setHttpClient(HttpClient client) {
		this.client = client;
	}
	
	private HttpClient httpClient() {
		return null == client ? Factory.getHttpClient(): client;
	}
	
}
